home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / elm / elm2.4 / src / save_opts.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-04-11  |  9.7 KB  |  412 lines

  1.  
  2. static char rcsid[] = "@(#)$Id: save_opts.c,v 5.2 1993/04/12 03:10:54 syd Exp $";
  3.  
  4. /*******************************************************************************
  5.  *  The Elm Mail System  -  $Revision: 5.2 $   $State: Exp $
  6.  *
  7.  *            Copyright (c) 1988-1992 USENET Community Trust
  8.  *            Copyright (c) 1986,1987 Dave Taylor
  9.  *******************************************************************************
  10.  * Bug reports, patches, comments, suggestions should be sent to:
  11.  *
  12.  *    Syd Weinstein, Elm Coordinator
  13.  *    elm@DSI.COM            dsinc!elm
  14.  *
  15.  *******************************************************************************
  16.  * $Log: save_opts.c,v $
  17.  * Revision 5.2  1993/04/12  03:10:54  syd
  18.  * The onoff macro assumes a boolean option only has values 1 or 0.
  19.  * This is not true for forms option (may be 2 == MAYBE).
  20.  *
  21.  * This is known bug EB51 BTW. I'm looking at the list now and there are some
  22.  * bugs that I think are simple, and I'll try to fix some of them.
  23.  * From: Jan Djarv <Jan.Djarv@sa.erisoft.se>
  24.  *
  25.  * Revision 5.1  1992/10/03  22:58:40  syd
  26.  * Initial checkin as of 2.4 Release at PL0
  27.  *
  28.  *
  29.  ******************************************************************************/
  30.  
  31. /** This file contains the routine needed to allow the users to change the
  32.     Elm parameters and then save the configuration in a ".elm/elmrc" file in
  33.     their home directory.  With any luck this will allow them never to have
  34.     to actually EDIT the file!!
  35.  
  36. **/
  37.  
  38. #include "headers.h"
  39. #include "s_elmrc.h"
  40. #include <errno.h>
  41.  
  42. #undef onoff
  43. #define   onoff(n)    (n == 0? "OFF":"ON")
  44.  
  45. #define absolute(x)        ((x) < 0? -(x) : (x))
  46.  
  47. extern  int errno;
  48. extern char version_buff[];
  49.  
  50. char *error_description(), *sort_name(), *alias_sort_name(), *level_name();
  51. long  ftell();
  52.  
  53. #include "save_opts.h"
  54.  
  55. FILE *elminfo;        /* informational file as needed... */
  56.  
  57. save_options()
  58. {
  59.     /** Save the options currently specified to a file.  This is a
  60.         fairly complex routine since it tries to put in meaningful
  61.         comments and such as it goes along.  The comments are
  62.         extracted from the file ELMRC_INFO as defined in the sysdefs.h
  63.         file.  THAT file has the format;
  64.  
  65.         varname
  66.           <comment>
  67.           <comment>
  68.         <blank line>
  69.  
  70.         and each comment is written ABOVE the variable to be added.  This
  71.         program also tries to make 'pretty' stuff like the alternatives
  72.         and such.
  73.     **/
  74.  
  75.     FILE *newelmrc; 
  76.     char  oldfname[SLEN], newfname[SLEN];
  77.  
  78.     sprintf(newfname, "%s/%s", home, elmrcfile);
  79.     sprintf(oldfname, "%s/%s", home, old_elmrcfile);
  80.  
  81.     /** first off, let's see if they already HAVE a .elm/elmrc file **/
  82.  
  83.     save_file_stats(newfname);
  84.     if (access(newfname, ACCESS_EXISTS) != -1) {
  85.       /** YES!  Copy it to the file ".old.elmrc".. **/
  86.       if (rename(newfname, oldfname) < 0)
  87.         dprint(2, (debugfile, "Unable to rename %s to %s\n", 
  88.            newfname, oldfname));
  89.       (void) chown(oldfname, userid, groupid);
  90.  
  91.     }
  92.  
  93.     /** now let's open the datafile if we can... **/
  94.  
  95.     if ((elminfo = fopen(ELMRC_INFO, "r")) == NULL) 
  96.       error1(catgets(elm_msg_cat, ElmrcSet, ElmrcSavingWithoutComments,
  97.           "Warning: saving without comments! Can't get to %s."), 
  98.           ELMRC_INFO);
  99.  
  100.     /** next, open the new .elm/elmrc file... **/
  101.  
  102.     if ((newelmrc = fopen(newfname, "w")) == NULL) {
  103.        error2(catgets(elm_msg_cat, ElmrcSet, ElmrcCantSaveConfig,
  104.            "Can't save configuration! Can't write to %s [%s]."),
  105.            newfname, error_description(errno));
  106.        return;
  107.     }
  108.     
  109.     save_user_options(elminfo, newelmrc);
  110.     restore_file_stats(newfname);
  111.  
  112.     error1(catgets(elm_msg_cat, ElmrcSet, ElmrcOptionsSavedIn,
  113.         "Options saved in file %s."), newfname);
  114. }
  115.  
  116. static char *str_opt(x, f)
  117. register int x;
  118. int f;
  119. {
  120.     static char buf[SLEN];
  121.     register char *s, *t;
  122.  
  123.     s = strcpy(buf, "*ERROR*");
  124.     switch(save_info[x].flags & DT_MASK) {
  125.         case DT_STR:
  126.         if (save_info[x].flags & FL_NOSPC) {
  127.             for (t = SAVE_INFO_STR(x), s = buf; *t; ++t, ++s)
  128.             if ((*s = *t) == SPACE) *s='_';
  129.             *s = '\0';
  130.             s = buf;
  131.         } else
  132.             s = SAVE_INFO_STR(x);
  133.         break;
  134.  
  135.         case DT_CHR:
  136.         sprintf(buf, "%c", *SAVE_INFO_CHR(x));
  137.         s = buf;
  138.         break;
  139.  
  140.         case DT_BOL:
  141.         s = onoff(*SAVE_INFO_BOL(x));
  142.         break;
  143.  
  144.         case DT_SRT:
  145.         if (f == FULL) {
  146.             s = sort_name(SHORT);
  147.             break;
  148.         }
  149.         sprintf(buf, "%d", *SAVE_INFO_NUM(x));
  150.         s = buf;
  151.         break;
  152.  
  153.         case DT_ASR:
  154.         if (f == FULL) {
  155.             s = alias_sort_name(SHORT);
  156.             break;
  157.         }
  158.         sprintf(buf, "%d", *SAVE_INFO_NUM(x));
  159.         s = buf;
  160.         break;
  161.  
  162.         case DT_NUM:
  163.         if (f == FULL) {
  164.             if (equal(save_info[x].name, "userlevel")) {
  165.             s = level_name(*SAVE_INFO_NUM(x));
  166.             break;
  167.             }
  168.         }
  169.         sprintf(buf, "%d", *SAVE_INFO_NUM(x));
  170.         s = buf;
  171.         break;
  172.  
  173.         default:
  174.         break;
  175.     }
  176.     return(s);
  177. }
  178.  
  179. find_opt(s)
  180. char *s;
  181. {
  182.     register int x, y;
  183.  
  184.     for (x = 0; x < NUMBER_OF_SAVEABLE_OPTIONS; x++) {
  185.         y = strcmp(s, save_info[x].name);
  186.         if (y <= 0)
  187.         break;
  188.     }
  189.  
  190.     if (y != 0)
  191.         return(-1);
  192.     return(x);
  193. }
  194.  
  195. char *str_opt_nam(s, f)
  196. char *s;
  197. int f;
  198. {
  199.     char *t = NULL;
  200.     int x;
  201.  
  202.     x = find_opt(s);
  203.     if (x >= 0)
  204.         t = str_opt(x, f);
  205.     return(t);
  206. }
  207.  
  208.  
  209. save_user_options(elminfo_fd, newelmrc)
  210. FILE *elminfo_fd, *newelmrc;
  211. {
  212.     register int x, local_value;
  213.     register char *s;
  214.  
  215.     /** save the information in the file.  If elminfo_fd == NULL don't look
  216.         for comments!
  217.     **/
  218.  
  219.     if (elminfo_fd != NULL) 
  220.       build_offset_table(elminfo_fd);
  221.  
  222.     fprintf(newelmrc, catgets(elm_msg_cat, ElmrcSet, ElmrcOptionsFile,
  223.           "#\n# .elm/elmrc - options file for the ELM mail system\n#\n"));
  224.  
  225.     if (strlen(full_username) > 0)
  226.       MCfprintf(newelmrc, catgets(elm_msg_cat, ElmrcSet, ElmrcSavedAutoFor,
  227.           "# Saved automatically by ELM %s for %s\n#\n\n"),
  228.           version_buff, full_username);
  229.     else
  230.       fprintf(newelmrc, catgets(elm_msg_cat, ElmrcSet, ElmrcSavedAuto,
  231.         "# Saved automatically by ELM %s\n#\n\n"), version_buff);
  232.  
  233.     fprintf(newelmrc, catgets(elm_msg_cat, ElmrcSet, ElmrcYesNoMeans,
  234.         "# For yes/no settings with ?, ON means yes, OFF means no\n"));
  235.  
  236.     for (x = 0; x < NUMBER_OF_SAVEABLE_OPTIONS; x++) {
  237.         char buf[SLEN];
  238.  
  239.         /** skip system-only options **/
  240.         if (save_info[x].flags & FL_SYS)
  241.         continue;
  242.  
  243.         local_value = save_info[x].flags & FL_LOCAL;
  244.         s="";
  245.         switch(save_info[x].flags & DT_MASK) {
  246.         case DT_MLT:
  247.         case DT_SYN:
  248.             break;
  249.  
  250.         case DT_ASR:
  251.         case DT_SRT:
  252.             s = str_opt(x, FULL);
  253.             break;
  254.  
  255.         case DT_STR:
  256.         case DT_CHR:
  257.         case DT_BOL:
  258.         case DT_NUM:
  259.             s = str_opt(x, SHORT);
  260.             break;
  261.  
  262.         case DT_WEE:
  263.             { int len = 0 ,i;
  264.  
  265.             add_comment(x, newelmrc);
  266.             if (!local_value)
  267.                 fprintf(newelmrc, "### ");
  268.             fprintf(newelmrc, "%s = ", save_info[x].name);
  269.             len = strlen(save_info[x].name) + 4;
  270.  
  271.             for (i = 0; i < weedcount && strcmp(weedlist[i], "*end-of-defaults*") !=0; i++)
  272.                 /* intentional null loop body */;
  273.  
  274.             while (i < weedcount && equal(weedlist[i], "*end-of-defaults*"))
  275.                 i++;
  276.  
  277.             while (i < weedcount) {
  278.                 if (strlen(weedlist[i]) + len > 78) {
  279.                 if (local_value)
  280.                     fprintf(newelmrc, "\n\t");
  281.                 else
  282.                     fprintf(newelmrc, "\n###\t");
  283.                 len = 8;
  284.                 }
  285.                 fprintf(newelmrc, "\"%s\" ", weedlist[i]);
  286.                 len += strlen(weedlist[i]) + 4;
  287.                 ++i;
  288.             }
  289.             fprintf(newelmrc, "\t\"*end-of-user-headers*\"\n");
  290.             }
  291.             break;
  292.  
  293.         case DT_ALT:
  294.             {   struct addr_rec *alts;
  295.             int len=0;
  296.  
  297.             alts = *SAVE_INFO_ALT(x);
  298.             if (!alts) break;
  299.  
  300.             add_comment(x, newelmrc);
  301.             if (!local_value)
  302.                 fprintf(newelmrc, "### ");
  303.             fprintf(newelmrc, "%s = ", save_info[x].name);
  304.             len = strlen(save_info[x].name) + 4;
  305.             for ( ;alts; alts = alts->next) {
  306.                 if (strlen(alts->address) + len > 78) {
  307.                 if (local_value)
  308.                     fprintf(newelmrc, "\n\t");
  309.                 else
  310.                     fprintf(newelmrc, "\n###\t");
  311.                 len = 8;
  312.                 }
  313.             fprintf(newelmrc, "%s ", alts->address);
  314.             len += strlen(alts->address) + 2;
  315.             }
  316.             }
  317.             fprintf(newelmrc,"\n");
  318.             break;
  319.         }
  320.  
  321.         if (*s) {
  322.         add_comment(x, newelmrc);
  323.         if (local_value)
  324.             fprintf(newelmrc, "%s = %s\n", save_info[x].name, s);
  325.         else
  326.             fprintf(newelmrc, "### %s = %s\n", save_info[x].name, s);
  327.         }
  328.         }
  329.  
  330.     fclose(newelmrc);
  331.     if ( elminfo_fd != NULL ) {
  332.         fclose(elminfo_fd);
  333.     }
  334. }
  335.  
  336. add_comment(iindex, fd)
  337. int iindex;
  338. FILE *fd;
  339. {    
  340.     /** get to and add the comment to the file **/
  341.     char buffer[SLEN];
  342.  
  343.     /** always put a blank line between options */
  344.     fputc('\n', fd);
  345.  
  346.     /** add the comment from the comment file, if available **/
  347.     if (save_info[iindex].offset > 0L) {
  348.       if (fseek(elminfo, save_info[iindex].offset, 0) == -1) {
  349.         dprint(1,(debugfile,
  350.            "** error %s seeking to %ld in elm-info file!\n",
  351.            error_description(errno), save_info[iindex].offset));
  352.       }
  353.       else {
  354.         while (fgets(buffer, SLEN, elminfo) != NULL) {
  355.           if (buffer[0] != '#') 
  356.         break;
  357.           fputs(buffer, fd);
  358.         }
  359.       }
  360.     }
  361. }
  362.  
  363. build_offset_table(elminfo_fd)
  364. FILE *elminfo_fd;
  365. {
  366.     /** read in the info file and build the table of offsets.
  367.         This is a rather laborious puppy, but at least we can
  368.         do a binary search through the array for each element and
  369.         then we have it all at once!
  370.     **/
  371.  
  372.     char line_buffer[SLEN];
  373.     
  374.     while (fgets(line_buffer, SLEN, elminfo_fd) != NULL) {
  375.       if (strlen(line_buffer) > 1)
  376.         if (line_buffer[0] != '#' && !whitespace(line_buffer[0])) {
  377.            no_ret(line_buffer);
  378.            if (find_and_store_loc(line_buffer, ftell(elminfo_fd))) {
  379.              dprint(1, (debugfile,"** Couldn't find and store \"%s\" **\n", 
  380.              line_buffer));
  381.            }
  382.         }
  383.     }
  384. }
  385.  
  386. find_and_store_loc(name, offset)
  387. char *name;
  388. long  offset;
  389. {
  390.     /** given the name and offset, find it in the table and store it **/
  391.  
  392.     int first = 0, last, middle, compare;
  393.  
  394.     last = NUMBER_OF_SAVEABLE_OPTIONS;
  395.  
  396.     while (first <= last) {
  397.  
  398.       middle = (first+last) / 2;
  399.  
  400.       if ((compare = strcmp(name, save_info[middle].name)) < 0) /* a < b */
  401.         last = middle - 1;
  402.       else if (compare == 0) {                    /* a = b */
  403.         save_info[middle].offset = offset;
  404.         return(0);
  405.       }
  406.       else  /* greater */                        /* a > b */
  407.         first = middle + 1; 
  408.     }
  409.  
  410.     return(-1);
  411. }
  412.